package megrez.oss.local.web;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import megrez.oss.common.FileNameCounter;
import megrez.oss.common.StringHelper;
import megrez.oss.local.components.FileData;
import megrez.oss.local.components.StorageComponent;
import megrez.oss.local.domain.Metadata;
import megrez.oss.local.domain.MetadataRepository;
import megrez.oss.local.domain.MetadataService;

/**
 * 文件接口
 *  
 * @author Lucky Yang
 * @since 2.6.9
 */
@RestController
@RequestMapping("/v1/files")
public class FileResouce {
    @Autowired
	private StorageComponent storage;
	@Autowired
	private MetadataService metadataSrc;
	@Autowired
	private MetadataRepository metadataRepo;

    @PostMapping("/upload")
	@ResponseStatus(HttpStatus.CREATED)
	public MetadataVO upload(@RequestParam("file") MultipartFile file) {
		return MetadataVO.withPO(storage.store(file));
	}
 
	@GetMapping("/download/{metadataId}")
	public void download(@PathVariable String metadataId, final HttpServletResponse response)
			throws IOException {
		Metadata md = metadataSrc.findById(metadataId);

		// 文件数据
		final FileData fileData = storage.download(md);
		// 设置响应
		response.setContentType(fileData.metadata.getContentType());
		response.setHeader("Content-Disposition",
				String.format("inline; filename=\"%s\"", StringHelper.convertChartSet(fileData.metadata.getName(), StandardCharsets.UTF_8)));
		FileCopyUtils.copy(fileData.content.getInputStream(), response.getOutputStream());
	}    

	@GetMapping(value = "/downloads")
	public void downloads(@RequestParam(name = "metadataIds") Set<String> metadataIds,
			HttpServletResponse response) throws IOException {
		final byte[] buffer = new byte[2048];
		// 查询元数据
		List<Metadata> metadataList = metadataRepo.findAllById(metadataIds);
		try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
				ZipOutputStream zos = new ZipOutputStream(baos)) {
			FileNameCounter fileNameCounter = new FileNameCounter();

			for (Metadata md : metadataList) {
				FileData fileData = storage.download(md);
				// 避免重复的文件名
				ZipEntry zipEntry = new ZipEntry(fileNameCounter.count(fileData.metadata.getName()));
				zos.putNextEntry(zipEntry);

				InputStream is = fileData.content.getInputStream();
				int bytesRead;
				while ((bytesRead = is.read(buffer)) != -1) {
					zos.write(buffer, 0, bytesRead);
				}

				zos.closeEntry();
			}
			// 解决‘文件末端错误’
			zos.finish();

			response.setContentType("application/zip");
			response.addHeader("Pragma", "no-cache");
			response.addHeader("Expires", "0");
			final ServletOutputStream sos = response.getOutputStream();
			sos.write(baos.toByteArray());
			sos.flush();
		}
	}

	@DeleteMapping("/{metadataId}")
	public MetadataVO remove(@PathVariable String metadataId) {
		Metadata md = metadataSrc.findById(metadataId);
		storage.remove(md);
		return MetadataVO.withPO(md);
	}    
}
